package borge.web.teamspirit.client.servercomm;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import borge.web.teamspirit.client.interfaces.PersistentData.DataKey;

@SuppressWarnings("serial")
// @PersistenceCapable(identityType = IdentityType.APPLICATION)
public class DBQuery implements Serializable {

	// Types
	public static final String SELECT = "select from ";
	public static final String DELETE = "delete from ";

	// Filter operators
	public static final String EQUALS = " == ";
	public static final String NOT_EQUAlS = " != ";
	public static final String GREATER_THAN = " > ";
	public static final String LESS_THAN = " < ";
	public static final String GREATER_THAN_OR_EQUALS = " >= ";
	public static final String LESS_THAN_OR_EQUALS = " <= ";

	// Logical operators
	public static final String AND = " && ";
	public static final String OR = " || ";

	public static final String ASCENDING = " asc ";
	public static final String DESCENDING = " desc ";

	private static final String COMMA_SEPARATOR = ", ";

	// @PrimaryKey
	// @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	// @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
	private String iEncodedKey;

	private String iSessionId;

	private String iType;
	// Full package name of entity
	// @Persistent
	private String iClass;
	
	private DataKey iDataKey;

	// List of query filters
	// @Persistent
	private List<QueryFilter> iQueryFilters;

	// @Persistent
	private List<Serializable> iParamValues;

	// Comma separated list of field orderings
	// @Persistent
	private String iOrdering;

	// @Persistent
	private Integer iRangeStart;

	// @Persistent
	private Integer iRangeEnd;

	static class QueryFilter implements Serializable {
		private String iFieldName;
		private String iOperator;
		private String iParamName;
		private String iParamType;
		// public String iParamValue;
		private String iLogicalSeparator;

		public QueryFilter() {

		}

		public QueryFilter(String aFN, String aOp, String aPN, String aPT,
				String aLS) {
			iFieldName = aFN;
			iOperator = aOp;
			iParamName = aPN;
			iParamType = aPT;
			// iParamValue = aPV;
			iLogicalSeparator = aLS;
		}
	}

	public DBQuery(){
		iQueryFilters = new ArrayList<QueryFilter>();
	}
	
	public DBQuery(DataKey aKey, String aClass) {
		this();
		iDataKey = aKey;
		iClass = aClass;
		iType = DBQuery.SELECT;
	}

	public DBQuery(DataKey aKey, String aType, String aClass) {
		this(aKey, aType);
		iClass = aClass;
	}

	public String getQuery() {

		StringBuffer buffer = new StringBuffer();

		buffer.append(iType);
		buffer.append(iClass);

		if (iQueryFilters.size() > 0) {

			buffer.append(" where ");

			// Add filters
			for (QueryFilter filter : iQueryFilters) {

				buffer.append(filter.iFieldName);
				buffer.append(filter.iOperator);
				buffer.append(filter.iParamName);

				if (filter.iLogicalSeparator != null)
					buffer.append(filter.iLogicalSeparator);
			}

			buffer.append(" parameters ");

			// Add param declarations
			boolean addComma = false;
			for (QueryFilter filter : iQueryFilters) {

				if (addComma)
					buffer.append(", ");
				buffer.append(filter.iParamType);
				buffer.append(" ");
				buffer.append(filter.iParamName);
				addComma = true;
			}
		}

		// Add ordering
		if (iOrdering != null) {
			buffer.append(" order by ");
			buffer.append(iOrdering);
		}

		return buffer.toString();
	}

	/*
	 * DBQuery query = new DBQuery();
	 * query.setDataClass("borge.web.teamspirit.client.data.Person");
	 * query.addFilter("iUserName", DBQuery.EQUALS, "String", "usernameParam",
	 * input.getUserName()); query.addLogicalAnd(); query.addFilter("iPassword",
	 * DBQuery.EQUALS, "String", "passwordParam", input.getPassword());
	 */

	public void addFilter(String aFieldName, String aOperator,
			String aParamName, String aParamType, String aParamValue,
			String aLogical) {
		addFilter(new QueryFilter(aFieldName, aOperator, aParamName,
				aParamType, aLogical));

		if (iParamValues == null)
			iParamValues = new ArrayList<Serializable>();
		iParamValues.add(aParamValue);
	}

	private void addFilter(QueryFilter aFilter) {
		iQueryFilters.add(aFilter);
	}

	public void setType(String aType) {
		iType = aType;
	}

	public String getType() {
		return iType;
	}

	public void setDataKey(DataKey aKey){
		iDataKey = aKey;
	}
	
	public DataKey getDataKey(){
		return iDataKey;
	}
	
	public void setEntityClassName(String aClass) {
		this.iClass = aClass;
	}

	public String getEntityClassName() {
		return iClass;
	}

	public List<Serializable> getParamValues() {
		return iParamValues;
	}

	public void addOrdering(String aFieldName, String aOrder) {
		if (this.iOrdering == null)
			this.iOrdering = aFieldName.trim() + aOrder;
		else
			this.iOrdering += COMMA_SEPARATOR + aFieldName.trim() + aOrder;
	}

	public String getOrdering() {
		return iOrdering;
	}

	public void setRange(int aStart, int aEnd) {
		iRangeStart = aStart;
		iRangeEnd = aEnd;
	}

	public int getRangeStart() {
		return iRangeStart;
	}

	public int getRangeEnd() {
		return iRangeEnd;
	}
}
